package com.sa35.fbs.dao.util;

import java.util.List;
import java.util.Set;


import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Junction;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DaoUtil {

	protected static final Logger logger = LoggerFactory.getLogger(DaoUtil.class);

	/**
	 * A utility method to get the first element of a list.
	 * User of this method must be aware that result of this method call may be
	 * null if list provided is empty or null.
	 *
	 * @return first element of a list. returns null if list is empty.
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getFirstElement(List<?> elements) {
		assert elements != null;
		if(elements.size() > 0) {
			if (logger.isDebugEnabled()) {
				if (elements.size() > 1) {
					// if the query naturally return more than 1 but you're
					// only interested in the latest, consider limiting the result
					// using: findByCriteria(criteria, 0, 1)
					logger.debug("Query {} return {} results", new Exception().getStackTrace()[1], elements.size());
				}

			}
			return (T) elements.get(0);
		}

		return null;
	}

	public static int extractCount(List<?> elements) {
		assert !elements.isEmpty();
		return (Integer) elements.get(0);
	}

	public static Criterion isNullOrEquals(String propertyName, Object value) {
		return value == null ? Restrictions.isNull(propertyName) : Restrictions.eq(propertyName, value);
	}
	
	public static void addIdInCriteria(DetachedCriteria criteria, String criteriaFieldName, Set<Long> ids) {
		int collSize = ids.size();
		if (collSize > 1000) {
			List<Set<Long>> separatedIdList = SqlUtil.oneThousandSeparationForSqlINClause(ids);
			
			Junction batchJunction = Restrictions.disjunction();
			for (int x = 0; x < separatedIdList.size(); x++)
			{
				batchJunction.add(Restrictions.in(criteriaFieldName, separatedIdList.get(x)));
			}
			criteria.add(batchJunction);
		} else {
			criteria.add(Restrictions.in(criteriaFieldName, ids));
		}
	}

	
	public static void addIdInCriteria(DetachedCriteria criteria, String criteriaFieldName, List<Long> ids) {
		int collSize = ids.size();
		if (collSize > 1000) {
			List<List<Long>> separatedIdList = SqlUtil.oneThousandSeparationForSqlINClause(ids);
			
			Junction batchJunction = Restrictions.disjunction();
			for (int x = 0; x < separatedIdList.size(); x++)
			{
				batchJunction.add(Restrictions.in(criteriaFieldName, separatedIdList.get(x)));
			}
			criteria.add(batchJunction);
		} else {
			criteria.add(Restrictions.in(criteriaFieldName, ids));
		}
	}
	
	private DaoUtil() {}

}
